from enum import Enum

import math


def _move_circle(size, point, r, duration, n=1, clock_direction=True):
    """
    圆周移动
    :param size:
      Can be either
        - ``(width,height)`` in pixels or a float representing
        - A function of time returning one of these.
    :param point: 圆心坐标
    :param r: 半径
      Can be either
         - radius
         - A function
    :param duration:时长
    :param n: 旋转n圈, 默认1圈
    :param clock_direction: Ture,顺时针
    :return:
    """
    (x0, y0) = point
    w = math.pi * 2.0 * n / duration
    direction = 1 if clock_direction else -1
    if not hasattr(size, "__call__"):
        size_func = lambda t: size
    else:
        size_func = size
    if not hasattr(r, "__call__"):
        r_func = lambda t: r
    else:
        r_func = r
    return lambda t: (
        (x0 - size_func(t)[0] / 2) + r_func(t) * math.cos(direction * w * t),
        (y0 - size_func(t)[1] / 2) + r_func(t) * math.sin(direction * w * t))


def _move_line(size, point1, point2, duration):
    """
    线性移动
    :param size:
      Can be either
        - ``(width,height)`` in pixels or a float representing
        - A function of time returning one of these.
    :param point1: 开始起坐标点
    :param point2: 最终坐标点
    :param duration: 时长
    :return:
    """
    if not hasattr(size, "__call__"):
        size_func = lambda t: size
    else:
        size_func = size
    return lambda t: (point1[0] - size_func(t)[0] / 2 + 1.0 * (point2[0] - point1[0]) * t / duration,
                      point1[1] - size_func(t)[1] / 2 + 1.0 * (point2[1] - point1[1]) * t / duration)


def _move_screw_spin(size, point1, point2, r, duration, n=1, clock_direction=True):
    """
    螺旋移动
    :param size:
      Can be either
        - ``(width,height)`` in pixels or a float representing
        - A function of time returning one of these.
    :param point1: 开始起坐标点
    :param point2: 最终坐标点
    :param r: 半径
      Can be either
        - radius
        - A function    :param duration:时长
    :param n: 旋转n圈, 默认1圈
    :param clock_direction: Ture,顺时针
    :return:
    """
    (x1, y1) = point1
    (x2, y2) = point2
    angle = math.atan(1.0 * (y2 - y1) / (x2 - x1))
    w = math.pi * 2.0 * n / duration
    direction = 1 if clock_direction else -1
    vx = 1.0 * (x2 - x1) / duration
    vy = 1.0 * (y2 - y1) / duration
    if not hasattr(size, "__call__"):
        size_func = lambda t: size
    else:
        size_func = size
    if not hasattr(r, "__call__"):
        r_func = lambda t: r
    else:
        r_func = r
    return lambda t: (
        (x1 - size_func(t)[0] / 2 + vx * t) + r_func(t) * math.cos(angle - math.pi + direction * w * t),
        (y1 - size_func(t)[1] / 2 + vy * t) + r_func(t) * math.sin(angle - math.pi + direction * w * t))


class MoveFunctions(Enum):
    line = _move_line
    circle = _move_circle
    screw_spin = _move_screw_spin
